#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <signal.h>
#include <errno.h>
#include <unistd.h>

#include "funcutil.h"
#include "readconf.h"
#include "global.h"
#include "logger.h"


namespace wb
{

static void start_worker_proc(int tnums);
static int spawn_process(int tid, const char* procname);
static void worker_cycle(int id, const char* procname);
static void worker_init(int id);

static const char* master_name = "master process";

void master_cycle()
{
    sigset_t set;
    sigemptyset(&set);

    sigaddset(&set, SIGCHLD);
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO);
    sigaddset(&set, SIGINT);
    sigaddset(&set, SIGHUP);
    sigaddset(&set, SIGTERM);
    sigaddset(&set, SIGQUIT);

    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
    {
        Logger::logger_core(LogLevel::Error, errno, "master_cycle() sigprocmask() failed");
    }

    start_worker_proc(cfg.worker);

    sigemptyset(&set);

    for (;;)
    {
        sigsuspend(&set);
        sleep(1);
    } //end for(;;)

    return ;
}

static void start_worker_proc(int tnums)
{
    for (int i = 0; i < tnums; ++i)
    {
        spawn_process(i, "worker process");
    }
    return ;
}

static int spawn_process(int id, const char* name)
{
    pid_t tpid;
    tpid = fork();
    switch (tpid)
    {
    case -1:
        Logger::logger_core(LogLevel::Error, errno, "spawn_process() fork() id = %d, procname = %s failed", id, name);
        return -1;
    case 0:
        ppid = pid;
        pid = getpid();
        worker_cycle(id, name); //真正的打工仔在这里
        break;
    default:
        break;
    }
    return tpid;
}

static void worker_cycle(int id, const char* name)
{
    isMaster = false;
    worker_init(id);
    Logger::logger_core(LogLevel::Info, 0, "%s %P [worker process] starts and running...", name, pid);

    for (;;)
    {
        process_events_and_timers();
    }

    g_threadpool.StopAll();
    //g_Socket.shutdown();

    return ;
}

static void worker_init(int id)
{
    sigset_t set;
    sigemptyset(&set);

    if (sigprocmask(SIG_SETMASK, &set, NULL) == -1)
    {
        Logger::logger_core(LogLevel::Error, errno, "worker_init() sigprocmask() failed");
    }

    int threadnums = cfg.worker; //cfg.threadnums;
    if (g_threadpool.Create(threadnums) == false)
    {
        exit(-2);
    }
    sleep(1);

    if (g_Socket.Initialize() == false) //
    {
        exit(-2);
    }

    g_Socket.epollInit();

    return ;
}




}
